package com.woniu.inlet.listen;

import com.rabbitmq.client.Channel;
import com.woniu.adapter.BuyRateAdapter;
import com.woniu.adapter.DailyCodeValuationAdapter;
import com.woniu.outlet.client.OrderMessage;
import com.woniu.outlet.client.UpdateOrderStatus;
import com.woniu.outlet.mysql.ReceivedMsgFGOrderPayDao;
import com.woniu.outlet.mysql.po.BuyRateMySQL;
import com.woniu.outlet.mysql.po.DailyCodeTOne;
import com.woniu.outlet.mysql.po.ReceivedMsgFGOrderPayMySQL;
import com.woniu.service.UserDetailService;
import com.woniu.service.bean.AddEarnings;
import com.woniu.service.bean.UpdateBuyRecord;
import com.woniu.service.domain.UserDetail;
import com.woniu.util.AppUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;

/**
 * 监听支付成功的订单信息
 */
@Slf4j
@Component
@RabbitListener(queues = "order_buy_fg_pay")
public class FunfGoldBuyOrderListener {

    @Autowired
    private ReceivedMsgFGOrderPayDao receivedMsgFGOrderPayDao;
    @Autowired
    private DailyCodeValuationAdapter dailyCodeValuationAdapter;
    @Autowired
    private UpdateOrderStatus updateOrderStatus;
    @Autowired
    private OrderMessage orderMessage;
    @Autowired
    private BuyRateAdapter buyRateAdapter;
    @Autowired
    private UserDetailService userDetailService;

    @Transactional // 抛出异常，事务回滚。
    @RabbitHandler
    public void handle(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {

        String[] strings = message.split("!");
        if (strings.length < 2) {
            channel.basicReject(tag, false);
            throw new RuntimeException("接收到的消息内容格式错误");
        }

        // 消息的第一部分是：消息在【可靠消息服务】那边的消息表中的ID（唯一）。
        String messageIdString = strings[0];
        Integer messageId = Integer.parseInt(messageIdString);

        // 消息的第二部分是：订单模块发送过来的具体消息 。
        String substring = strings[1];
        // 去掉字符串最后的字符
        String orderList = substring.substring(0, substring.length() - 1);
        String[] orders = orderList.split(",");

        try {
            // 1. 判断是否是重复消息：insert into 去重表
            receivedMsgFGOrderPayDao.insert(new ReceivedMsgFGOrderPayMySQL(null, messageId));
        } catch (RuntimeException e) {
            log.debug("该消息重复");
            // 2. 拒绝消息。要求 RabbitMQ 从队列中删除。
            channel.basicReject(tag, false);
            return;
        }

        try {
            // 执行本地业务逻辑
            log.debug("执行本地业务逻辑");
            UpdateBuyRecord orderSucceed = new UpdateBuyRecord();

            for (String order : orders) {
                String[] order1 = order.split("/");
                //交易金额
                BigDecimal dealPrice = new BigDecimal(order1[2]);
                log.debug("交易金额为{}", dealPrice);
                orderSucceed.setUserId(Integer.parseInt(order1[1])); //user id
                orderSucceed.setDealTime(AppUtils.getNowTimeStr()); //交易时间
                orderSucceed.setDealPrice(dealPrice); //交易金额
                orderSucceed.setProductType(order1[3]); //产品类型
                orderSucceed.setProductCode(order1[4]); //产品code
                orderSucceed.setId(Integer.valueOf(order1[5]));
                log.debug("接收到的买入交易表数据id{}", Integer.valueOf(order1[5]));
                //计算手续费
                BuyRateMySQL buyRateMSQLByMoney = buyRateAdapter.getBuyRateMSQLByMoney(dealPrice);
                //手续费费率
                Double rate = buyRateMSQLByMoney.getRate();
                log.debug("手续费费率为{}", rate);
                //手续费
                BigDecimal cost = dealPrice.multiply(new BigDecimal(rate.toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
                log.debug("手续费为{}", cost);
                orderSucceed.setDealCharge(cost);

                //计算份额
                DailyCodeTOne dailyCodeTOne = dailyCodeValuationAdapter.getDailyCodeValuationMySQL(orderSucceed.getProductCode());

                //份额=（交易金额-手续费）/净值
                BigDecimal todayValuation = dailyCodeTOne.getTodayValuation();
                BigDecimal share = orderSucceed.getDealPrice().subtract(cost).divide(todayValuation, 4, BigDecimal.ROUND_HALF_UP);
                log.debug("购买份额为{}", share);

                //将消息添加到支付成功的数据表
                orderSucceed.execute();

                //修改订单状态
                updateOrderStatus.updateStatus0To1(Long.valueOf(order1[0]),
                        cost.toString(),
                        share.doubleValue());

                //更新用户的总资产
                //根据userid查询用户
                UserDetail user = userDetailService.getMoneyByUserId(Integer.parseInt(order1[1]));
                UserDetail userDetail = new UserDetail();
                userDetail.setUserId(user.getUserId());
                userDetail.setTotalAmount(user.getTotalAmount().add(dealPrice.subtract(cost)));
                userDetailService.updateUser(userDetail);
                //向用户模块发送消息
                String inform = "";
                //获取基金的名字
                DailyCodeTOne dailyCodeValuationMySQL = dailyCodeValuationAdapter.getDailyCodeValuationMySQL(order1[4]);
                if (order1[3].equals("fund")) {
                    inform = "您好，您已成功购买的【基金】:" + dailyCodeValuationMySQL.getName() + "。" + "-" + order1[1] + "-" + "y";
                } else {
                    inform = "您好，您已成功购买的【黄金】:" + dailyCodeValuationMySQL.getName() + "。" + "-" + order1[1] + "-" + "y";
                }
                orderMessage.sendMessage("pay.inform.user", "pay_inform_user", inform);
                //向平台收益表添加数据
                AddEarnings addEarnings = new AddEarnings();
                addEarnings.setUserId(Integer.parseInt(order1[1])); //userId
                addEarnings.setDealPrice(dealPrice); //交易金额
                addEarnings.setDealCharge(cost); //手续费
                addEarnings.setDealTime(AppUtils.getNowTimeStr());
                addEarnings.setDealType(AddEarnings.BUY);
                addEarnings.setProductType(order1[3]);
                addEarnings.execute();
            }
            // 确认接收，并处理该消息
            channel.basicAck(tag, false);
            // 发起 HTTP 请求: http://可靠消息服务/message/{}/received"
            orderMessage.receivedMessage(messageId);
        } catch (RuntimeException e) {
            // 执行本地业务出错，拒绝消息，要求 RabbitMQ 从队列中删除。
            // 等待发送者的定时器下次再发送一次。
            channel.basicReject(tag, false);
            throw new NullPointerException();
        }
    }
}
